#pragma once
#include <QHash>
#include <QDebug>
#include <QString>
#include <QSharedPointer>
#include <QMetaType>

#include <string>
#include <google/protobuf/message.h>

#include "utils.h"
#include "type.h"

namespace apollo
{
	namespace core
	{
		
		class Payload
		{
		public:// message type
			static const qint16 MESSAGE_TYPE_HELLO = 1;
			static const qint16 MESSAGE_TYPE_HELLO_2 = 2;
			static const qint16 MESSAGE_TYPE_LOGIN = 3;
			static const qint16 MESSAGE_TYPE_LOGIN_SUCCESS= 4;
			static const qint16 MESSAGE_TYPE_LOGIN_ERROR = 5;
			static const qint16 MESSAGE_TYPE_LOGOUT = 6;
			static const qint16 MESSAGE_TYPE_APP = 0xFF;
		public: // header key
			static QString DTO_TYPE;
			static QString SESSION_ID;
		public:
			static const char KEY_VALUE_SPLITTER = '=';
			static const char HEADER_SPLITTER = '\n';

		private:
			quint32 messageId;
			quint16 messageType;
			QHash<QString, QString> header;
			qint32 bodySize;
			char* body;
		public:
			Payload(void);
			~Payload(void);
		public:
			quint32 getMessageId() const {return messageId;}
			void setMessageId(quint32 msgId) {messageId = msgId;}
			quint16 getMessageType() const {return messageType;}
			void setMessageType(quint16 type) {messageType = type;}
			void setHeader(const QString& headerStr);
			const QString getHeader(const QString& key) const;
			QString getHeader() const;
			void addHeader(const QString &key, const QString &value);
			void removeHeader(const QString &key);
			qint32 getBodySize() const {return bodySize;}
			void setBodySize(qint32 size) {bodySize = size;}
			const char* const getBody() const {return body;}
			void setBody(char* body) {this->body = body;}
			void setBody(const google::protobuf::Message* message);
			MessagePtr getMessage() const;
		private:
			
		}; //class payload
		typedef  QSharedPointer<Payload> PayloadPtr;

		inline QDebug& operator<<(QDebug& debug, PayloadPtr payload)
		{
			debug << "<< Received: id = " << payload->getMessageId() << "type:" 
				<< payload->getMessageType() << "header:" << payload->getHeader() << "Body:"
				<<  Utils::toHexRepresentation(payload->getBody(), payload->getBodySize());
			return debug;
		}

	}//namespace core
}//namespace apollo
Q_DECLARE_METATYPE(apollo::core::Payload)
Q_DECLARE_METATYPE(apollo::core::PayloadPtr)